home *** CD-ROM | disk | FTP | other *** search
/ Utilities Professional 1-1500 / Utilities Professional 1-1500 (1994)(WPD)[!].iso / 12511500 / var1449.dms / var1449.adf / AudioDevice / Example1.c < prev    next >
C/C++ Source or Header  |  1992-04-27  |  10KB  |  369 lines

  1. /***********************************************************/
  2. /*                                                         */
  3. /* Amiga C Encyclopedia (ACE) V3.0      Amiga C Club (ACC) */
  4. /* -------------------------------      ------------------ */
  5. /*                                                         */
  6. /* Book:    ACM Devices                 Amiga C Club       */
  7. /* Chapter: AudioDevice                 Tulevagen 22       */
  8. /* File:    Example1.c                  181 41  LIDINGO    */
  9. /* Author:  Anders Bjerin               SWEDEN             */
  10. /* Date:    92-04-21                                       */
  11. /* Version: 1.00                                           */
  12. /*                                                         */
  13. /*   Copyright 1992, Anders Bjerin - Amiga C Club (ACC)    */
  14. /*                                                         */
  15. /* Registered members may use this program freely in their */
  16. /*     own commercial/noncommercial programs/articles.     */
  17. /*                                                         */
  18. /***********************************************************/
  19.  
  20. /* This program will play some notes (A to G#)     */
  21. /* with help of the Audio Device. It will use      */
  22. /* one of the audio channels (the first one which  */
  23. /* is free).                                       */
  24.  
  25.  
  26.  
  27. #include <exec/types.h>        /* STRPTR         */
  28. #include <exec/memory.h>       /* MEMF_CHIP      */
  29. #include <devices/audio.h>     /* Audio Device   */
  30.  
  31.  
  32.  
  33. /* The audio channels: (Sadly these constants */
  34. /* have not been defined in any header file.) */ 
  35.  
  36. /* Values: */
  37. #define LEFT0B   0
  38. #define RIGHT0B  1
  39. #define RIGHT1B  2
  40. #define LEFT1B   3
  41.  
  42. /* Bit fields: */
  43. #define LEFT0F   (1<<LEFT0B)
  44. #define RIGHT0F  (1<<RIGHT0B)
  45. #define RIGHT1F  (1<<RIGHT1B)
  46. #define LEFT1F   (1<<LEFT1B)
  47.  
  48. /* Sound priorities: */
  49. #define SOUND_UNSTOPPABLE  127
  50. #define SOUND_EMERGENCIES   95
  51. #define SOUND_ATTENTION     85
  52. #define SOUND_SPEECH        75
  53. #define SOUND_INFORMATION   60
  54. #define SOUND_MUSIC          0
  55. #define SOUND_EFFECT       -35
  56. #define SOUND_BACKGROUND   -90
  57. #define SOUND_SILENCE     -128
  58.  
  59. /* The clock constant: */
  60. #define NTSC_CLOCK    3579545 /* American Amigas - 60Hz */
  61. #define PAL_CLOCK     3546895 /* European Amigas - 50Hz */
  62.  
  63.  
  64.  
  65. /* Some common notes (their frequencies are */
  66. /* defined later on in this program):       */
  67. #define NOTE_A   0
  68. #define NOTE_Ax  1
  69. #define NOTE_B   2
  70. #define NOTE_C   3
  71. #define NOTE_Cx  4
  72. #define NOTE_D   5
  73. #define NOTE_Dx  6
  74. #define NOTE_E   7
  75. #define NOTE_F   8
  76. #define NOTE_Fx  9
  77. #define NOTE_G  10
  78. #define NOTE_Gx 11
  79.  
  80. /* An octave consists of 12 notes: */
  81. #define OCTAVE  12
  82.  
  83. /* Define min/max-volumes: */
  84. #define MAXVOLUME  64
  85. #define MINVOLUME   0
  86.  
  87. /* Our square waveform data consists of two samples: */
  88. /* (Waveform data must alwyas be an even number of   */
  89. /* byte long.)                                       */
  90. #define SQUARE_DATA_LENGTH 2
  91.  
  92.  
  93.  
  94. /* Declare a pointer to our reply port: */
  95. struct MsgPort *replymp = NULL;
  96.  
  97. /* Declare a pointer to our audio request block: */
  98. struct IOAudio *audio_req = NULL;
  99.  
  100.  
  101.  
  102. /* Our list of preffered channel combinations: */
  103. /* (First we try to reserve the first channel, */
  104. /* then the second, third and finally fourth   */
  105. /* audio channel.)                             */
  106. UBYTE allocation_array[]=
  107. {
  108.   LEFT0F,
  109.   RIGHT0F,
  110.   RIGHT1F,
  111.   LEFT1F
  112. };
  113.  
  114. /* Declare a pointer to some soundwave data: */
  115. BYTE *square_wave = NULL;
  116.  
  117.  
  118.  
  119. /* The notes (defined above) frequencies. These frequencies      */
  120. /* represent notes which are one octave higher than the middle   */
  121. /* octave on a piano. To change octave, simply double/half these */
  122. /* values. Ex, A=880, one octave lower A=440, one octave higher  */
  123. /* A=1760.                                                       */
  124. /*                                                               */
  125. /* Instead of changing the frequencies you can of course double  */
  126. /* or half the amount of samled waveform data. If you double the */
  127. /* amount of sampled waveformdata you will move down one octave  */
  128. /* and vice versa. In this example when we caluculate the period */
  129. /* value we use the length of the vaweform as one parameter.     */
  130. /* Therefore, if you change the length of the waveform the same  */
  131. /* frequencies will be used.                                     */ 
  132.  
  133. UWORD note_frequency[ OCTAVE ]=
  134. {
  135.    880.0, /* A  */
  136.    932.3, /* A# */
  137.    987.8, /* B  */
  138.   1046.5, /* C  */
  139.   1108.7, /* C# */
  140.   1174.7, /* D  */
  141.   1244.5, /* D# */
  142.   1318.5, /* E  */
  143.   1396.9, /* F  */
  144.   1480.0, /* F# */
  145.   1568.0, /* G  */
  146.   1661.2  /* G# */
  147. };
  148.  
  149.  
  150.  
  151. /* Declare our functions: */
  152. void main();
  153. void clean_up( STRPTR text );
  154.  
  155.  
  156.  
  157. void main()
  158. {
  159.   /* Error messages: */
  160.   BYTE error;
  161.  
  162.   /* The channel we have received: */
  163.   UBYTE channel;
  164.  
  165.   /* Used in the loops: */
  166.   int note;
  167.  
  168.  
  169.  
  170.   /* Get a reply port: (No name, priority 0) */
  171.   replymp = (struct MsgPort *)
  172.     CreatePort( NULL, 0 );
  173.   if( !replymp )
  174.     clean_up( "Could not create the reply port!" );
  175.  
  176.  
  177.  
  178.   /* Allocate and preinitialize an audio request block: */
  179.   audio_req = (struct IOAudio *)
  180.     CreateExtIO( replymp, sizeof( struct IOAudio ) );
  181.   if( !audio_req )
  182.     clean_up( "Not enough memory for the IOAudio structure!" );
  183.  
  184.  
  185.  
  186.   /* Open the Audio Device: (We will try to */
  187.   /* reserve a sound channel later on.)     */
  188.   error = OpenDevice( AUDIONAME, 0, audio_req, 0 );
  189.   if( error )
  190.   {
  191.     /* Clear the "io_Device" flag since we have not opened the device: */
  192.     audio_req->ioa_Request.io_Device = NULL;
  193.   
  194.     /* Quit: */
  195.     clean_up( "Could not open the Audio Device!" );
  196.   }
  197.  
  198.  
  199.  
  200.   /* Try to reserve a channel: */
  201.   audio_req->ioa_Request.io_Command = ADCMD_ALLOCATE;
  202.  
  203.   /* Set sound priority: (We are going to play some music.) */
  204.   audio_req->ioa_Request.io_Message.mn_Node.ln_Pri = SOUND_MUSIC;
  205.  
  206.   /* Do not wait for any channels to be free, */
  207.   /* return immediately, successfully or not: */
  208.   audio_req->ioa_Request.io_Flags = ADIOF_NOWAIT;
  209.  
  210.   /* Give the request block a pointer to our allocation array: */
  211.   audio_req->ioa_Data = allocation_array;
  212.   
  213.   /* Set the length of the allocation array: */
  214.   audio_req->ioa_Length = sizeof( allocation_array );
  215.          
  216.   /* Do our request: */
  217.   BeginIO( audio_req );
  218.  
  219.   /* Wait for the request to be completed: */
  220.   error = WaitIO( audio_req );
  221.  
  222.   /* Everything OK? */
  223.   if( error )
  224.     clean_up( "No channel available!" );
  225.  
  226.  
  227.  
  228.   /* Check which channel we received: */
  229.   channel = (UBYTE) audio_req->ioa_Request.io_Unit;
  230.  
  231.   if( channel & LEFT0F )
  232.     printf( "First left channel!\n" );
  233.  
  234.   if( channel & RIGHT0F )
  235.     printf( "First right channel!\n" );
  236.  
  237.   if( channel & RIGHT1F )
  238.     printf( "Second right channel!\n" );
  239.  
  240.   if( channel & LEFT1F )
  241.     printf( "Second left channel!\n" );
  242.  
  243.  
  244.  
  245.   /* Allocate some memory where we can store the waveform we   */
  246.   /* want to use. Note that it must be Chip memory, and placed */
  247.   /* on a word boundary!                                       */
  248.   square_wave = (BYTE *) AllocMem( SQUARE_DATA_LENGTH, MEMF_CHIP );
  249.   if( !square_wave )
  250.     clean_up( "Could not allocate enough memory for the square wave!" );  
  251.  
  252.   /* Initialize the waveform: (This is the smallest    */
  253.   /* waveform you can use, and undouptly the easiest.) */
  254.   square_wave[ 0 ] = 127;
  255.   square_wave[ 1 ] = -127;
  256.  
  257.  
  258.  
  259.   
  260.   /* Give the request block a pointer to the waveform: */
  261.   audio_req->ioa_Data = square_wave;
  262.  
  263.   /* Set the length of the waveform:    */
  264.   /* (Must be an even number of bytes.) */
  265.   audio_req->ioa_Length = SQUARE_DATA_LENGTH;
  266.  
  267.   /* Play the waveform 100 times: */
  268.   audio_req->ioa_Cycles = 200;
  269.  
  270.   /* Going to play a tune: */
  271.   audio_req->ioa_Request.io_Command = CMD_WRITE;
  272.  
  273.   /* Use the volume and period fields of the request block: */
  274.   /* (If we do not set this flag the previous volume and    */
  275.   /* period values will be used.)                           */
  276.   audio_req->ioa_Request.io_Flags = ADIOF_PERVOL;
  277.  
  278.   /* Medium volume: */
  279.   audio_req->ioa_Volume = 32;
  280.  
  281.  
  282.  
  283.   /* Tell the user to be prepared: */
  284.   printf( "Here comes some notes: (A to G#)\n" );
  285.   printf( "Ahh, almost as nice as a PC!...\n" );
  286.   printf( "Note the \"klicking\" noice between the tones.\n" );
  287.  
  288.   /* Play one octave: */
  289.   for( note=0; note < OCTAVE; note++ )
  290.   {
  291.     /* Set the period: The period value is calculated with help of the */
  292.     /* formula: period = clock / frequency / sampled bytes             */
  293.     audio_req->ioa_Period =
  294.       PAL_CLOCK / note_frequency[ note ] / SQUARE_DATA_LENGTH;
  295.  
  296.     /* Set a mark: */
  297.     printf( "*" );
  298.  
  299.     /* Start to play a note: */
  300.     BeginIO( audio_req );
  301.     
  302.     /* Wait for the note to be completed: */
  303.     error = WaitIO( audio_req );
  304.  
  305.     /* Was the note successfully played? */
  306.     if( error )
  307.       clean_up( "Error!" );
  308.   }
  309.  
  310.  
  311.   /* Clean up and quit: */
  312.   clean_up( "The End!" );
  313. }
  314.  
  315.  
  316.  
  317. /* Close and return everything that has been */
  318. /* opened and allocated before we quit:      */
  319.  
  320. void clean_up( STRPTR text )
  321. {
  322.   /* If we have a request block and it does not contain   */
  323.   /* any errors we know that a channel has been allocated */
  324.   /* and must be deallocated:                             */
  325.   if( audio_req && !(audio_req->ioa_Request.io_Error) )
  326.   {
  327.     /* Free the channel: */
  328.     audio_req->ioa_Request.io_Command = ADCMD_FREE;
  329.  
  330.     /* We are allowed to use the function DoIO() for */
  331.     /* this request since it will not change any     */
  332.     /* values that are vital for us:                 */ 
  333.     DoIO( audio_req );
  334.     
  335.     /* The lock is automatically unlocked when we */
  336.     /* free the audio channel.                    */
  337.   }
  338.  
  339.   /* Empty the reply port: */
  340.   while( GetMsg( replymp ) )
  341.     printf( "Collected a message at the reply port.\n" );
  342.   
  343.   /* If we have a request block and the "io_Device" field  */
  344.   /* is not zero, we know that the device has successfully */
  345.   /* been opened and must now be closed:                   */ 
  346.   if( audio_req && audio_req->ioa_Request.io_Device )
  347.     CloseDevice( audio_req );
  348.  
  349.   /* Remove the replyport: */
  350.   if( replymp )
  351.     DeletePort( replymp);
  352.  
  353.   /* Dealocate the IOAudio structure: */
  354.   if( audio_req )
  355.     DeleteExtIO( audio_req, sizeof( struct IOAudio ) );
  356.  
  357.   /* Dealocate the square waveform: */
  358.   if( square_wave )
  359.     FreeMem( square_wave, SQUARE_DATA_LENGTH );
  360.  
  361.   /* Print the last message: */
  362.   printf( "%s\n", text );
  363.  
  364.   /* Quit: */
  365.   exit( 0 );
  366. }
  367.  
  368.  
  369.